using System.Text;
using System.Threading;
using Mina.Core.Session;
using Mina.Filter.Codec;

namespace Com.FirstSolver.Splash;

public class FaceReaderProtocolCodecFactory : IProtocolCodecFactory
{
	internal static SM2 sm2 = new SM2();

	private readonly FaceReaderEncoderAdapter Encoder;

	private readonly FaceReaderDecoderAdapter Decoder;

	public FaceReaderProtocolCodecFactory(bool isPassiveEncryption = false, ManualResetEvent encryptionReadyEvent = null)
	{
		Encoder = new FaceReaderEncoderAdapter();
		Decoder = new FaceReaderDecoderAdapter(isPassiveEncryption, encryptionReadyEvent);
	}

	public IProtocolEncoder GetEncoder(IoSession session)
	{
		return Encoder;
	}

	public IProtocolDecoder GetDecoder(IoSession session)
	{
		return Decoder;
	}

	internal static void SetEncoderKey(IoSession session, byte[] secretKey, int mode)
	{
		FaceReaderEncoderAdapter.SetSecretKey(session, secretKey, mode);
	}

	internal static void SetDecoderKey(IoSession session, byte[] secretKey, int mode)
	{
		FaceReaderDecoderAdapter.SetSecretKey(session, secretKey, mode);
	}

	public static void EnablePassiveEncryption(IoSession session, bool isServer = false, SM2UserInformation userInfo = null)
	{
		if (userInfo == null)
		{
			if (!isServer)
			{
				COMMAND_AKE_TYPE Command = new COMMAND_AKE_TYPE();
				Command.COMMAND = "AKE";
				session.Write(Command.ToJsonString());
			}
			return;
		}
		SM2KeyExchangeInformation Information = new SM2KeyExchangeInformation();
		Information.PrivateKey = userInfo.PrivateKey;
		Information.PublicKey = new FpPoint(sm2.mCurve, sm2.mCurve.FromBigInteger(userInfo.PublicKeyX), sm2.mCurve.FromBigInteger(userInfo.PublicKeyY), withCompression: false);
		Information.r = sm2.GetKeyPair(out Information.R);
		Information.Z = sm2.ComputeZ(Encoding.UTF8.GetBytes(userInfo.OwnerId), Information.PublicKey);
		session.SetAttribute(FaceReaderDecoderAdapter.KEY_SM2KEYEXCHANGEINFORMATION, Information);
		if (isServer)
		{
			session.SetAttribute(FaceReaderDecoderAdapter.KEY_SM2OWNERID, userInfo.OwnerId);
			return;
		}
		COMMAND_AKE_TYPE Command2 = new COMMAND_AKE_TYPE();
		Command2.COMMAND = "AKE";
		Command2.PARAM = new PARAM_COMMAND_AKE_TYPE();
		Command2.PARAM.sn = userInfo.OwnerId;
		Command2.PARAM.key = new string[2];
		StringBuilder sb = new StringBuilder(128);
		sb.Append(Utils.ToString(sm2.GetEncoded(Information.PublicKey.mX)));
		sb.Append(Utils.ToString(sm2.GetEncoded(Information.PublicKey.mY)));
		Command2.PARAM.key[0] = sb.ToString();
		sb.Clear();
		sb.Append(Utils.ToString(sm2.GetEncoded(Information.R.mX)));
		sb.Append(Utils.ToString(sm2.GetEncoded(Information.R.mY)));
		Command2.PARAM.key[1] = sb.ToString();
		session.Write(Command2.ToJsonString());
	}

	public static void EnablePassiveEncryption(IoSession session, string SN, bool isServer = false, SM2UserInformation userInfo = null)
	{
		if (userInfo == null)
		{
			if (!isServer)
			{
				COMMAND_AKE_TYPE Command = new COMMAND_AKE_TYPE();
				Command.COMMAND = "AKE";
				Command.PARAM = new PARAM_COMMAND_AKE_TYPE();
				Command.PARAM.sn = SN;
				session.Write(Command.ToJsonString());
			}
			return;
		}
		SM2KeyExchangeInformation Information = new SM2KeyExchangeInformation();
		Information.PrivateKey = userInfo.PrivateKey;
		Information.PublicKey = new FpPoint(sm2.mCurve, sm2.mCurve.FromBigInteger(userInfo.PublicKeyX), sm2.mCurve.FromBigInteger(userInfo.PublicKeyY), withCompression: false);
		Information.r = sm2.GetKeyPair(out Information.R);
		Information.Z = sm2.ComputeZ(Encoding.UTF8.GetBytes(userInfo.OwnerId), Information.PublicKey);
		session.SetAttribute(FaceReaderDecoderAdapter.KEY_SM2KEYEXCHANGEINFORMATION, Information);
		if (isServer)
		{
			session.SetAttribute(FaceReaderDecoderAdapter.KEY_SM2OWNERID, userInfo.OwnerId);
			return;
		}
		COMMAND_AKE_TYPE Command2 = new COMMAND_AKE_TYPE();
		Command2.COMMAND = "AKE";
		Command2.PARAM = new PARAM_COMMAND_AKE_TYPE();
		Command2.PARAM.sn = userInfo.OwnerId;
		Command2.PARAM.key = new string[2];
		StringBuilder sb = new StringBuilder(128);
		sb.Append(Utils.ToString(sm2.GetEncoded(Information.PublicKey.mX)));
		sb.Append(Utils.ToString(sm2.GetEncoded(Information.PublicKey.mY)));
		Command2.PARAM.key[0] = sb.ToString();
		sb.Clear();
		sb.Append(Utils.ToString(sm2.GetEncoded(Information.R.mX)));
		sb.Append(Utils.ToString(sm2.GetEncoded(Information.R.mY)));
		Command2.PARAM.key[1] = sb.ToString();
		session.Write(Command2.ToJsonString());
	}
}
